package com.iflytek.shiro;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.iflytek.bean.Admin;
import com.iflytek.bean.Role;
import com.iflytek.service.AdminService;
import com.iflytek.service.RoleService;


//继承AuthorizingRealm可以同时完成认证和授权两个操作
public class UserRealm extends AuthorizingRealm{
	
	@Autowired
	private AdminService adminService;
	
	@Autowired
	private RoleService roleService;
	
	//定义这个Realm的名称
	@Override
	public String getName() {
		return "UserRealm";
	}

	//授权，此方法返回用户所拥有的角色和权限
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		List<String> roles = new ArrayList<String>(); //用户的角色列表

	    Admin admin = (Admin)principals.getPrimaryPrincipal();  //获取当前登录的用户
	    
	    //根据管理员id查询该管理员所拥有的角色
	    List<Role> roleList = roleService.findAdminRoles(admin.getId());
	    //把角色列表转换成String类型的角色列表
	    for(Role r : roleList) {
	    	roles.add(r.getRoleCode());
	    }
	    
	    //用户的权限列表
	    List<String> permissions = roleService.findAdminPermissions(admin.getId());
	    System.out.println(permissions);
	    //将用户的角色和权限封装成SimpleAuthorizationInfo对象，交给shiro管理，需要的时候用于授权
	    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
	    info.addRoles(roles);
	    info.addStringPermissions(permissions);

	    return info;
	}

	//认证
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String username = (String)token.getPrincipal();   //获取用户登录时提交的用户名
		Admin admin = adminService.findAdminByUsername(username);  //根据用户名到数据库查询该管理员信息
		if(admin == null) { //没有该管理员信息，说明用户名错误，直接返回null
			return null;
		}
		
		//将认证信息封装并返回，SecurityManager会自动将用户提交的信息与此认证信息比对
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
				admin, 
				admin.getPassword(), 
				ByteSource.Util.bytes("thisisasalt"),   //指定加密的盐
				getName());
		return info;
	}

}
